/*
 * @Author: xiaosihan 
 * @Date: 2024-03-17 20:38:43 
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2024-03-17 20:49:51
 */

import MeshBase from "@views/home/component3d/MeshBase/MeshBase";
import Sky from "@views/home/component3d/Sky/Sky";
import { AmbientLight, Box3, DirectionalLight, Object3D, PerspectiveCamera, PointLight, Vector3 } from "three";
import ThreeBase from "three-base";
import threeUtils from "three-base/threeUtils";

/**
 * @class HomeRender
 * @extends {ThreeBase}
 */
class WindowRenderer extends ThreeBase {

    constructor() {
        super();
    }

    // 环境光
    ambientLight = (() => {
        const ambientLight = new AmbientLight("#fff", 2.0);
        this.scene.add(ambientLight);
        return ambientLight;
    })();

    //点光源
    pointLight = (() => {
        const pointLight = new PointLight("#fff", 2.0);
        pointLight.distance = 100;
        pointLight.decay = 0;
        pointLight.position.set(50, 40, 50);
        this.scene.add(pointLight);
        return pointLight;
    })();

    // 方向光
    directionalLight = (() => {
        const directionalLight = new DirectionalLight("#fff", 2.0);
        directionalLight.position.set(-10, 10, 5);
        directionalLight.target.position.set(0, 0, 0);
        directionalLight.castShadow = true;
        directionalLight.shadow.mapSize.set(1024, 1024);
        this.scene.add(directionalLight);
        return directionalLight;
    })();

    init() {
        super.init();
        this.gridHelper.visible = false;
        // this.controls.screenSpacePanning = false;
        // this.controls.panSpeed = 0;
        // this.resetLookAt({
        //     center: new Vector3(1.3, 2.903, -4.3),
        //     position: new Vector3(8.321, 5.403, -8.802),
        // });

        // 开发模式时还原记录的位置
        if (threeUtils.isDev && localStorage.dispaly_window_lookAt) {
            this.resetLookAt({
                ...JSON.parse(localStorage.dispaly_window_lookAt)
            });
        }

        // 开发模式时记录当前的位置
        if (threeUtils.isDev) {
            this.controls.addEventListener("change", () => {
                localStorage.dispaly_window_lookAt = JSON.stringify(this.getLookAt());
            })
        }

        if (threeUtils.isProd || (threeUtils.isDev && !localStorage.dispaly_window_lookAt)) {
            this.resetLookAt({
                center: new Vector3(1.5, -0.667, -4.735),
                position: new Vector3(1.5, 2, -4.735).add(new Vector3(10, 1, 0))
            });
        }

    }

    //天空
    sky = (() => {
        const sky = new Sky();
        this.scene.add(sky);
        return sky;
    })();

    // 窗户模型
    windwModal = (() => {
        const windwModal = new MeshBase();
        windwModal.addEventListener("loaded", () => {
            this.lookatObjects({
                objects: [windwModal],
                duration: 1000,
                direction: new Vector3(0, 0, 1),
                offset: new Vector3(0, 0, 0),
            });
        });
        this.scene.add(windwModal);
        return windwModal;
    })();

    // 查看对象
    lookatObjects({
        objects,
        duration = 1000,
        direction = new Vector3(0.3, 0.3, 1),
        offset = new Vector3(0, 0, 0),
        distance = 1
    }: {
        objects: Array<Object3D>,
        duration?: number,
        direction?: Vector3,
        offset?: Vector3,
        distance?: number
    }) {
        const box3 = new Box3();
        objects.map(o => box3.expandByObject(o));
        const size = new Vector3();
        box3.getSize(size);
        const center = new Vector3();
        box3.getCenter(center);

        center.add(offset);
        const modelSize = size.length() * distance;
        const { fov } = this.camera as PerspectiveCamera;
        const cameraDistance = modelSize / (2 * Math.tan(fov * Math.PI / 360));
        const position = direction.setLength(cameraDistance).add(center);
        this.setLookAt({ center, position, duration });
    }

    render(): void {
        this.pointLight.position.copy(this.camera.position);
        super.render();
    }


}


const windowRenderer = window.windowRenderer = new WindowRenderer();

export default windowRenderer;